package com.dmz.workflow.listener;

import com.dmz.workflow.constant.ProcessDefinitionConstants;
import com.dmz.workflow.util.*;
import com.dmz.workflow.constant.MsgContentEnum;
import com.dmz.workflow.entity.StaffInfo;
import com.dmz.workflow.service.WorkflowNodeExtService;
import com.echronos.workflow.util.*;
import com.echronos.workflow.constant.ProcessConstants;
import com.dmz.workflow.entity.ProcessInstanceStatus;
import com.dmz.workflow.service.WorkflowProcessStatusService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.TaskService;
import org.flowable.engine.delegate.event.impl.FlowableActivityEventImpl;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class ProcessEndListener implements FlowableEventListener, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Autowired
    private TaskService taskService;

    @Autowired
    private WorkflowProcessStatusService workflowProcessStatusService;

    @Autowired
    private MessageContentWrapper messageContentWrapper;

    @Autowired
    private WorkflowNodeExtService workflowNodeExtService;

    @Override
    public void onEvent(FlowableEvent flowableEvent) {
        String processInstanceId = "";
        String curActId = "";
        String processDefinitionId = "";

        if (flowableEvent instanceof FlowableActivityEventImpl) {
            FlowableActivityEventImpl flowableActivityEvent = (FlowableActivityEventImpl) flowableEvent;
            processInstanceId = flowableActivityEvent.getProcessInstanceId();
            curActId = flowableActivityEvent.getActivityId();
            processDefinitionId = flowableActivityEvent.getProcessDefinitionId();
        }
        if (StringUtils.isEmpty(processInstanceId) || StringUtils.isEmpty(curActId) || StringUtils.isEmpty(processDefinitionId)) {
            return;
        }
        Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
        List<FlowElement> flowElements = (List<FlowElement>) process.getFlowElements();
        for (FlowElement flowElement : flowElements) {
            if (flowElement instanceof EndEvent && curActId.equals(flowElements.get(flowElements.size() - 1).getId())) {
                ProcessInstanceStatus processInstanceStatus = workflowProcessStatusService.selectInstanceByInstanceId(processInstanceId);
                ConcurrentHashMap<String, String> processInstanceStatusData = TemporaryStatus.getInstance().getProcessInstanceStatusData();
                CallBackComponent callBackComponent = (CallBackComponent) applicationContext.getBean("callBackComponent");
                if (ObjectUtils.isNotEmpty(processInstanceStatus)) {
                    // update instance status as end status
                    workflowProcessStatusService.updateStatusByProcessInstanceId(processInstanceId, ProcessConstants.PERSON_APPROVED_STATUS);
                    log.info("完成的审批流程：{}", processInstanceId);
                    // 圈层价审批通过回调
                    if (ProcessConstants.PROCESS_INSTANCE_CIRCLE_PRICE_TYPE.equals(processInstanceStatus.getProcessInstanceType())) {
                        // 排除拒绝结束的回调
                        if (ObjectUtils.isEmpty(processInstanceStatusData.get(processInstanceId))) {
                            callBackComponent.circlePriceCallBack(processInstanceId, ProcessConstants.PROCESS_APPROVED_STATUS, null);
                        } else {
                            processInstanceStatusData.remove(processInstanceId);
                        }
                    }
                } else {
                    // deal instance end status when the process does not finish actually
                    processInstanceStatusData.put(processInstanceId, processInstanceId);
                }
                // check if the process finished normally , if it ended in order then send message to process starter
                if (ObjectUtils.isNotEmpty(processInstanceStatusData.get(processInstanceId))) {
                    ImcComponent imcComponent = (ImcComponent) applicationContext.getBean("imcComponent");
                    StaffInfo queryParams = new StaffInfo();
                    queryParams.setMemberId(processInstanceStatus.getStartUser());
                    queryParams.setProcessInstanceId(processInstanceId);
                    queryParams.setIdNode(ProcessDefinitionConstants.START_NODE_NAME);
                    StaffInfo staffInfo = workflowNodeExtService.selectPersonalNode(queryParams);
                    if (ObjectUtils.isNotEmpty(staffInfo)) {
                        imcComponent.imcAssistantSender(
                                messageContentWrapper.generateNotCommentMessageBody(MsgContentEnum.MESSAGE_FINISH_CONTENT, processInstanceId),
                                staffInfo.getUserId(),
                                Collections.singletonList(staffInfo.getUserId()), null);
                    }
                    processInstanceStatusData.remove(processInstanceId);
                    // 圈层价审批通过回调
                    if (ProcessConstants.PROCESS_INSTANCE_CIRCLE_PRICE_TYPE.equals(processInstanceStatus.getProcessInstanceType())) {
                        callBackComponent.circlePriceCallBack(processInstanceId, ProcessConstants.PROCESS_APPROVED_STATUS, null);
                    }
                }
            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
